﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.InfoCardXmlSerializer
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections;
using System.IdentityModel.Tokens;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Xml;
using System.Xml.Schema;

namespace Microsoft.InfoCards
{
  internal class InfoCardXmlSerializer
  {
    private InfoCard m_card;
    private X509Certificate2 m_issuer;
    private X509Certificate2Collection m_additionalIssuerCerts;
    private bool m_isIssuerChainTrusted;
    private bool m_checkSignature;
    private bool m_isDeserialized;
    private StoreConnection m_connection;

    public InfoCardXmlSerializer(StoreConnection connection)
    {
      this.m_connection = connection;
    }

    public InfoCard Card
    {
      get
      {
        if (this.m_isDeserialized)
          return this.m_card;
        return (InfoCard) null;
      }
    }

    public X509Certificate2 Issuer
    {
      get
      {
        if (this.m_isDeserialized)
          return this.m_issuer;
        return (X509Certificate2) null;
      }
    }

    public X509Certificate2Collection AdditionalIssuerCerts
    {
      get
      {
        return this.m_additionalIssuerCerts;
      }
    }

    public bool IsIssuerChainTrusted
    {
      get
      {
        InfoCardTrace.Assert(this.m_isDeserialized, "Card should be deserialized before checking this value");
        return this.m_isIssuerChainTrusted;
      }
    }

    public bool CheckSignature
    {
      set
      {
        this.m_checkSignature = value;
      }
    }

    public void Deserialize(string filename)
    {
      try
      {
        this.m_card = new InfoCard();
        this.m_card.HashSalt = InfoCard.GenerateSalt();
        this.CreateCardFromXml(filename);
        this.m_card.IssuerIdentifierAsBytes = Convert.FromBase64String(Recipient.CertGetRecipientOrganizationPPIDSeedHash(this.m_issuer, this.m_additionalIssuerCerts, this.m_isIssuerChainTrusted));
        this.m_isDeserialized = true;
      }
      catch (Exception ex)
      {
        if (!InfoCardTrace.IsFatal(ex))
          throw InfoCardTrace.ThrowHelperError((Exception) new ImportException(SR.GetString("InvalidImportFile"), ex));
        throw;
      }
    }

    private void CreateCardFromXml(string filename)
    {
      try
      {
        using (FileStream fileStream = File.OpenRead(filename))
        {
          using (XmlReader reader1 = InfoCardSchemas.CreateReader((Stream) fileStream, new XmlReaderSettings()
          {
            IgnoreWhitespace = false,
            IgnoreProcessingInstructions = false,
            IgnoreComments = true
          }))
          {
            this.RetrieveIssuerAndCheckSign(reader1);
            fileStream.Seek(0L, SeekOrigin.Begin);
            XmlReaderSettings defaultReaderSettings = InfoCardSchemas.CreateDefaultReaderSettings();
            defaultReaderSettings.IgnoreWhitespace = false;
            using (XmlReader reader2 = InfoCardSchemas.CreateReader((Stream) fileStream, defaultReaderSettings))
            {
              while (reader2.Read())
              {
                if (reader2.LocalName == "InformationCard")
                {
                  this.m_card.ReadXml(reader2);
                  break;
                }
              }
              reader2.Read();
              if ("Signature" != reader2.LocalName || XmlNodeType.EndElement != reader2.NodeType)
                throw InfoCardTrace.ThrowHelperError((Exception) new ImportException(SR.GetString("InvalidImportFile")));
            }
          }
        }
      }
      catch (XmlSchemaValidationException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new ImportException(SR.GetString("InvalidImportFile"), (Exception) ex));
      }
      catch (CryptographicException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new ImportException(SR.GetString("InvalidImportFile"), (Exception) ex));
      }
      catch (UnauthorizedAccessException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new ImportException(SR.GetString("ImportInaccesibleFile"), (Exception) ex));
      }
      catch (FileNotFoundException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new ImportException(SR.GetString("ImportFileNotFound"), (Exception) ex));
      }
      catch (IOException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new ImportException(SR.GetString("InvalidImportFile"), (Exception) ex));
      }
    }

    private void RetrieveIssuerAndCheckSign(XmlReader reader)
    {
      XmlDocument document = new XmlDocument();
      document.PreserveWhitespace = true;
      document.Load(reader);
      XmlNames.CreateNamespaceManager(document.NameTable);
      if ("Signature" != document.DocumentElement.LocalName && "http://www.w3.org/2000/09/xmldsig#" == document.DocumentElement.NamespaceURI)
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(SR.GetString("SignatureNotVerified")));
      SignedXml signedXml = new SignedXml(document);
      signedXml.LoadXml(document.DocumentElement);
      if (signedXml.Signature == null || signedXml.Signature.ObjectList == null || (signedXml.Signature.SignedInfo == null || signedXml.Signature.SignedInfo.References == null) || ((Reference) signedXml.Signature.SignedInfo.References[0]).TransformChain == null)
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(SR.GetString("SignatureNotVerified")));
      if (signedXml.Signature.ObjectList.Count != 1 || signedXml.Signature.SignedInfo.References.Count != 1 || ((Reference) signedXml.Signature.SignedInfo.References[0]).TransformChain.Count != 1)
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(SR.GetString("SignatureNotVerified")));
      string algorithm = ((Reference) signedXml.Signature.SignedInfo.References[0]).TransformChain[0].Algorithm;
      if (signedXml.Signature.SignedInfo.SignatureMethod != "http://www.w3.org/2000/09/xmldsig#rsa-sha1" || "http://www.w3.org/2001/10/xml-exc-c14n#" != algorithm && "http://www.w3.org/2001/10/xml-exc-c14n#WithComments" != algorithm || ("http://www.w3.org/2001/10/xml-exc-c14n#" != signedXml.Signature.SignedInfo.CanonicalizationMethodObject.Algorithm || "http://www.w3.org/2000/09/xmldsig#sha1" != ((Reference) signedXml.Signature.SignedInfo.References[0]).DigestMethod))
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(SR.GetString("SignatureNotVerified")));
      if (signedXml.KeyInfo == null)
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(SR.GetString("SignatureNotVerified")));
      XmlNodeList childNodes = signedXml.KeyInfo.GetXml().ChildNodes;
      KeyInfoX509Data keyInfoX509Data = new KeyInfoX509Data();
      foreach (XmlNode xmlNode in childNodes)
      {
        if ("http://www.w3.org/2000/09/xmldsig#" == xmlNode.NamespaceURI && "X509Data" == xmlNode.Name)
        {
          keyInfoX509Data.LoadXml((XmlElement) xmlNode);
          break;
        }
      }
      ArrayList certificates = keyInfoX509Data.Certificates;
      if (certificates == null || certificates.Count <= 0)
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(SR.GetString("NoCertificateFoundInSignature")));
      this.m_issuer = (X509Certificate2) certificates[0];
      this.m_additionalIssuerCerts = new X509Certificate2Collection();
      for (int index = 1; index < certificates.Count; ++index)
        this.m_additionalIssuerCerts.Add((X509Certificate2) certificates[index]);
      try
      {
        InfoCardX509Validator.ValidateChainOrPeer(this.m_issuer, this.m_additionalIssuerCerts, out this.m_isIssuerChainTrusted);
      }
      catch (SecurityTokenValidationException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(ex.Message));
      }
      if (this.m_checkSignature && !signedXml.CheckSignature(this.m_issuer, true))
        throw InfoCardTrace.ThrowHelperError((Exception) new IdentityValidationException(SR.GetString("SignatureNotVerified")));
    }
  }
}
